﻿//-----------------------------------------------------------------------
// <copyright file="Class.cs" company="FastNET Services">
//     Copyright (c) 2008-2009. All Rights Reserved.
// </copyright>
// <license>
//     GPLv2
// </license>
// <warranty>
//     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
//     BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
//     DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </warranty>
//-----------------------------------------------------------------------
#region Usings

using System;
using System.Text.RegularExpressions;
using GateShift.Common.Repository;
using GateShift.Common.Repository.Business;
using GateShift.Common.Repository.Interfaces.DataInterfaces;
using GateShift.Common.Repository.Interfaces.Factories;
using GateShift.Common.Repository.Interfaces.Repositories;

#endregion

namespace GateShift.Services.GameFramework.GameObjects
{
    /// <summary>
    /// Business class for managing all class related activity
    /// </summary>
    public class Class : IdentityBusinessBase<IClassData, IClassRepository>
    {
        #region CTor/DTor

        #region Creation Routines

        /// <summary>
        /// Initializes a new instance of the Class class
        /// </summary>
        public Class()
            : this(new RepositoryFactory())
        {
        }

        /// <summary>
        /// Initializes a new instance of the Class class
        /// </summary>
        /// <param name="factory">Factory for retrieving the Repository from</param>
        /// <exception cref="ArgumentNullException">Thrown if Factory is null</exception>
        public Class(IRepositoryFactory factory)
            : base(factory)
        {
        }

        #endregion

        #region Retrieve by ID

        /// <summary>
        /// Initializes a new instance of the Class class
        /// </summary>
        /// <param name="ID">Identity of the data to retrieve</param>
        /// <exception cref="ArgumentNullException">Thrown if ID is null</exception>
        public Class(Identity ID)
            : this(new RepositoryFactory(), ID)
        {
        }

        /// <summary>
        /// Initializes a new instance of the Class class
        /// </summary>
        /// <param name="factory">Factory for retrieving the Repository from</param>
        /// <param name="ID">Identity of the data to retrieve</param>
        /// <exception cref="ArgumentNullException">Thrown if Factory or ID are null</exception>
        public Class(IRepositoryFactory factory, Identity ID)
            : base(factory, ID)
        {
        }

        #endregion

        #region Retrieve by Data

        /// <summary>
        /// Initializes a new instance of the Class class
        /// </summary>
        /// <param name="factory">Factory for retrieving the Repository from</param>
        /// <param name="data">IClass of the data to retrieve</param>
        /// <exception cref="ArgumentNullException">Thrown if Factory or ID are null</exception>
        private Class(IRepositoryFactory factory, IClassData data)
            : base(factory, data)
        {
        }

        #endregion

        #endregion

        #region Data Properties

        /// <summary>
        /// Gets or sets the class name
        /// </summary>
        /// <exception cref="FormatException">Thown if the name is invalid</exception>
        /// <exception cref="ArgumentNullException">Thrown if the name is NULL or empty</exception>
        /// <exception cref="IndexOutOfRangeException">Thrown if the length is more than 20 characters</exception>
        public string Name
        {
            get
            {
                return Data.Name;
            }

            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    throw new ArgumentNullException("value", "A name must be specified");
                }

                if (value.Length > 20)
                {
                    throw new IndexOutOfRangeException(string.Format("Name is more than 20 Characters. Currently: {0}", value.Length));
                }

                if (!IsClassNameValid(value))
                {
                    throw new FormatException("Class name format is invalid. Check with IsClassNameValid.");
                }

                Data.Name = value;
            }
        }

        #endregion

        #region Attribute Modifiers

        /// <summary>
        /// Gets or sets the class's Accuracy Modifier
        /// </summary>
        public byte ModifierAccuracy
        {
            get
            {
                return Data.ModifierAccuracy;
            }

            set
            {
                Data.ModifierAccuracy = value;
            }
        }

        /// <summary>
        /// Gets or sets the class's Agility Modifier
        /// </summary>
        public byte ModifierAgility
        {
            get
            {
                return Data.ModifierAgility;
            }

            set
            {
                Data.ModifierAgility = value;
            }
        }

        /// <summary>
        /// Gets or sets the class's Endurance Modifier
        /// </summary>
        public byte ModifierEndurance
        {
            get
            {
                return Data.ModifierEndurance;
            }

            set
            {
                Data.ModifierEndurance = value;
            }
        }

        /// <summary>
        /// Gets or sets the class's Energy Modifier
        /// </summary>
        public byte ModifierEnergy
        {
            get
            {
                return Data.ModifierEnergy;
            }

            set
            {
                Data.ModifierEnergy = value;
            }
        }

        /// <summary>
        /// Gets or sets the class's Force Modifier
        /// </summary>
        public byte ModifierForce
        {
            get
            {
                return Data.ModifierForce;
            }

            set
            {
                Data.ModifierForce = value;
            }
        }

        /// <summary>
        /// Gets or sets the class's Insight Modifier
        /// </summary>
        public byte ModifierInsight
        {
            get
            {
                return Data.ModifierInsight;
            }

            set
            {
                Data.ModifierInsight = value;
            }
        }

        /// <summary>
        /// Gets or sets the class's Intellect Modifier
        /// </summary>
        public byte ModifierIntellect
        {
            get
            {
                return Data.ModifierIntellect;
            }

            set
            {
                Data.ModifierIntellect = value;
            }
        }

        /// <summary>
        /// Gets or sets the class's Strength Modifier
        /// </summary>
        public byte ModifierStrength
        {
            get
            {
                return Data.ModifierStrength;
            }

            set
            {
                Data.ModifierStrength = value;
            }
        }

        /// <summary>
        /// Gets or sets the class's Will Modifier
        /// </summary>
        public byte ModifierWill
        {
            get
            {
                return Data.ModifierWill;
            }

            set
            {
                Data.ModifierWill = value;
            }
        }

        #endregion

        #region Calculated Attributes

        /// <summary>
        /// Gets the class total Accuracy
        /// </summary>
        public short TotalAccuracy
        {
            get
            {
                return ModifierAccuracy;
            }
        }

        /// <summary>
        /// Gets the class total Agility
        /// </summary>
        public short TotalAgility
        {
            get
            {
                return ModifierAgility;
            }
        }

        /// <summary>
        /// Gets the class total Endurance
        /// </summary>
        public short TotalEndurance
        {
            get
            {
                return ModifierEndurance;
            }
        }

        /// <summary>
        /// Gets the class total Energy
        /// </summary>
        public short TotalEnergy
        {
            get
            {
                return ModifierEnergy;
            }
        }

        /// <summary>
        /// Gets the class total Force
        /// </summary>
        public short TotalForce
        {
            get
            {
                return ModifierForce;
            }
        }

        /// <summary>
        /// Gets the class total Insight
        /// </summary>
        public short TotalInsight
        {
            get
            {
                return ModifierInsight;
            }
        }

        /// <summary>
        /// Gets the class total Intellect
        /// </summary>
        public short TotalIntellect
        {
            get
            {
                return ModifierIntellect;
            }
        }

        /// <summary>
        /// Gets the class total Strength
        /// </summary>
        public short TotalStrength
        {
            get
            {
                return ModifierStrength;
            }
        }

        /// <summary>
        /// Gets the class total Will
        /// </summary>
        public short TotalWill
        {
            get
            {
                return ModifierWill;
            }
        }

        #endregion

        #region Public Static Validation Methods

        /// <summary>
        /// Tests whether or not a specified Class name is considered valid
        /// </summary>
        /// <param name="ClassName">Class Name to validate</param>
        /// <returns>Boolean of whether or not the class is valid</returns>
        /// <remarks> 1) Alphanumeric 2) First Character must be a letter 3) Maximum 20 characters</remarks>
        public static bool IsClassNameValid(string ClassName)
        {
            // First position must be alpha based, everything else can be alphanumeric and max of 20 characters
            Regex check = new Regex("^[a-zA-Z]{1}[a-zA-Z0-9]{0,19}$");

            return check.IsMatch(ClassName);
        }

        #endregion

        #region Public Validation Methods

        /// <summary>
        /// Validates the Class is valid
        /// </summary>
        /// <returns>Boolean based on the validity of the object</returns>
        public override bool IsValid()
        {
            // Check required fields
            if (string.IsNullOrEmpty(Data.Name))
            {
                return false;
            }

            //// TODO : Other values

            // Check the Values
            if (!IsClassNameValid(Data.Name))
            {
                return false;
            }

            // Everything passed by this point!
            return true;
        }

        #endregion
    }
}